#!/usr/bin/perl
# to select the overlap portion of 1_flow_table.csv, in particular, when sending rate of flow1 > flow

#folders
$root_folder="/home/dongjin2/SVNROOT/ethernet-switch";
$result_folder="$root_folder/rinse_test/2_to_1/exp6"; #root dir to store experimental resutls
$aggregated_result="$result_folder/linear_model_stats.csv"; #results for all experiments, used for plot

$num_pkts = 10000;
$packet_size=1500; #byte
#100Mb/s - 1000Mb/s, every 100Mb/s, slightly less than specified rate, according to real experiment
@flow1_send_rate=(-1,-1,-1,-1,-1,-1,-1,-1, 887.1e6,-1);
@flow2_send_rate=(99.081e6, 198.162e6, 295.875e6, 396.32e6, 495.404e6, 594.63e6, 691.28e6, 791.602e6, 887.624e6, 978e6);

#print "@flow1_send_rate\n";
#print "@flow2_send_rate\n";

@flow1_send_interval;
@flow2_send_interval;
for($i=0; $i<=$#flow1_send_rate; $i++)
{
	$flow1_send_interval[$i]=$packet_size*8.0/$flow1_send_rate[$i];
	$flow2_send_interval[$i]=$packet_size*8.0/$flow2_send_rate[$i];
}

print "@flow1_send_interval\n";
print "@flow2_send_interval\n";

@speed;
#specify sending rate
$start_sending_rate=100;#Mb/s
$end_sending_rate=1000;
$sending_rate_gap=100;
#calculate speed and gap (gap is not used for now)
for($b=$start_sending_rate, $a=0; $b<=$end_sending_rate; $b+=$sending_rate_gap, $a++)
{
	$speed[$a]=$b;
}

#flow1_rate, flow2_rate, flow_index, loss_rate, first_delay_time, first_delay_rate, 
#mean_loss_time, std_loss_time, mean_delay_time, std_delay_time, mean_delay_rate, std_delay_rate, mean_loss_episode, std_loss_episode
open(TOTAL_OUT, ">$aggregated_result") or die "$aggregated_result cannot be opened.\n";
print TOTAL_OUT "flow1_rate, flow2_rate, flow_index, loss_rate, first_delay_time, first_delay_rate, mean_loss_time, std_loss_time, mean_delay_time, std_delay_time, mean_delay_rate, std_delay_rate, mean_loss_episode, std_loss_episode\n";

#for($j=0; $j<=$#speed; $j++)
for($j=8; $j<=8; $j++)
{
	for($k=0; $k<=$#speed; $k++)
	#for($k=2; $k<=2; $k++)
	{
		chdir "$result_folder/$speed[$j]M/$speed[$k]M/real";
		print "folder = $result_folder/$speed[$j]M/$speed[$k]M/real\n";

		$in_flow="1_flow_table.csv";
		open(IN_FLOW, $in_flow) or die "$in_flow cannot be opened.\n";
		$line=<IN_FLOW>;
		chomp($line);
		@line_block=split(', ', $line);
		$arrival_time_start=$line_block[0];


		if($flow1_send_interval[$j]<=$flow2_send_interval[$k])
		{
			$end_time = $num_pkts*$flow1_send_interval[$j]+$arrival_time_start;
		}
		else
		{
			$end_time = $num_pkts*$flow2_send_interval[$k]+$arrival_time_start;			
		}
		print "end time = $end_time\n";

	for($i=1;$i<=2;$i++)
	{
		#extract <arrival time, delay> of every last packet before loss and first packet after loss
		print "Extracting packet before/after loss...\n";
		$in=$i . "_flow_table.csv";
		$out_before_after_loss=$i . "_flow_pkt_before_after_loss.csv";
		$out_loss_episode=$i . "_flow_loss_episode.txt";
		open(IN, $in) or die "$in cannot be opened.\n";
		open(OUT, ">$out_before_after_loss") or die "$out_before_after_loss cannot be opened.\n";
		open(OUT2, ">$out_loss_episode") or die "$out_loss_episode cannot be opened.\n";

		$prev_delay=-1;
		$prev_arrival_timestamp=-1;

		$line=<IN>;				
		chomp($line);
		@line_block=split(', ', $line);				
		$prev_arrival_timestamp=$line_block[0];
		$prev_delay=$line_block[3];
		print OUT "$prev_arrival_timestamp, 18\n";
	
		$local_loss_counter=0;
		$loss_counter=0;
		$total_counter=1;
				
		while(<IN>)
		{
			my($line)=$_;
			chomp($line);
			@line_block=split(', ', $line);

			if($line_block[0]>=$end_time)
			{
				last;
			}
				
			$cur_arrival_timestamp=$line_block[0];
			$cur_delay=$line_block[3];
			#print "cur_arrival_timestamp = $cur_arrival_timestamp, cur_delay = $cur_delay\n";
			#print "prev_arrival_timestamp = $prev_arrival_timestamp, prev_delay = $prev_delay\n";
				
			if($cur_delay==0)
			{
				$local_loss_counter=$local_loss_counter+1;
				$loss_counter=$loss_counter+1;
			}
			if($cur_delay==0 && $prev_delay>0) #found last packet before loss
			{
				print OUT "$prev_arrival_timestamp, $prev_delay\n";
				
			}
			elsif($prev_delay==0 && $cur_delay>0) #found first packet after loss
			{
				print OUT "$cur_arrival_timestamp, $cur_delay\n";
								
				print OUT2 "$local_loss_counter\n";
				$local_loss_counter=0;
			}		
			$prev_delay = $cur_delay;
			$prev_arrival_timestamp = $cur_arrival_timestamp;
		
			$total_counter=$total_counter+1;
		}

		close(IN);
		close(OUT);
		close(OUT2);			
	
		#further process flow_pkt_before_after_loss.csv if loss occured
		if($loss_counter<=0)
		{
			last;
		}

		$in=$i . "_flow_pkt_before_after_loss.csv";
		$out_loss_time=$i . "_flow_loss_time.txt";
		$out_delay_time=$i . "_flow_delay_time.txt";
		$out_delay_rate=$i . "_flow_delay_rate.txt";

		open(IN, $in) or die "$in cannot be opened.\n";
		open(OUT1, ">$out_loss_time") or die "$out_loss_time cannot be opened.\n";
		open(OUT2, ">$out_delay_time") or die "$out_delay_time cannot be opened.\n";
		open(OUT3, ">$out_delay_rate") or die "$out_delay_rate cannot be opened.\n";
		
		$line=<IN>;
		chomp($line);
		@line_block=split(', ', $line);
		$arrival_timestamp_first=$line_block[0];
		$delay_first=$line_block[1];

		$line=<IN>;
		chomp($line);
		@line_block=split(', ', $line);
		$arrival_timestamp=$line_block[0];
		$delay=$line_block[1];

		$first_delay_time=$arrival_timestamp-$arrival_timestamp_first;
		$first_delay_rate=($delay-$delay_first)/$first_delay_time;
		
		$prev_delay = $delay;
		$prev_arrival_timestamp = $arrival_timestamp;

		$loss_delay_flag=0; #0-process loss time, 1-process delay time

		while(<IN>)
		{
			$line=$_;
			chomp($line);
			@line_block=split(', ', $line);
			
			$arrival_timestamp=$line_block[0];
			$delay=$line_block[1];

			$diff_time=$arrival_timestamp-$prev_arrival_timestamp;
			if($loss_delay_flag==0)#loss
			{
				print OUT1 "$diff_time\n";
				$loss_delay_flag=1;
			}
			elsif($loss_delay_flag==1)#delay
			{
				if($diff_time!=0)
				{
					print OUT2 "$diff_time\n";
					$diff_delay=$delay-$prev_delay;
					$delay_rate=$diff_delay/$diff_time;
					print OUT3 "$delay_rate\n";
				}
				$loss_delay_flag=0;
			}

			$prev_delay = $delay;
			$prev_arrival_timestamp = $arrival_timestamp;
		}
		close(IN);
		close(OUT1);
		close(OUT2);
		close(OUT3);

		#calculate mean and std for loss_time, delay_time, delay_rate, loss_episode
		@array_loss_time=compute_avg_std($out_loss_time);
		@array_delay_time=compute_avg_std($out_delay_time);
		@array_delay_rate=compute_avg_std($out_delay_rate);
		@array_loss_episode=compute_avg_std($out_loss_episode);
		
		#format output
		$first_delay_time=$first_delay_time*(10**6);
		$array_loss_time[0]=$array_loss_time[0]*(10**6);
		$array_loss_time[1]=$array_loss_time[1]*(10**6);
		$array_delay_time[0]=$array_delay_time[0]*(10**6);
		$array_delay_time[1]=$array_delay_time[1]*(10**6);
		$array_delay_rate[0]=$array_delay_rate[0]/(10**6);
		$array_delay_rate[1]=$array_delay_rate[1]/(10**6);
	
		$formatted_first_delay_time=sprintf("%.3f", $first_delay_time);
		$formatted_array_loss_time[0]=sprintf("%.3f", $array_loss_time[0]);
		$formatted_array_loss_time[1]=sprintf("%.3f", $array_loss_time[1]);
		$formatted_array_delay_time[0]=sprintf("%.3f", $array_delay_time[0]);
		$formatted_array_delay_time[1]=sprintf("%.3f", $array_delay_time[1]);
		$formatted_array_delay_rate[0]=sprintf("%.3f", $array_delay_rate[0]);
		$formatted_array_delay_rate[1]=sprintf("%.3f", $array_delay_rate[1]);

		$loss_rate=$loss_counter*1.0/$total_counter;

		#total output
		#flow1_rate, flow2_rate, flow_index, loss_rate, first_delay_time, first_delay_rate, 
		#mean_loss_time, std_loss_time, mean_delay_time, std_delay_time, mean_delay_rate, std_delay_rate, mean_loss_episode, std_loss_episode
		print TOTAL_OUT "$speed[$j], $speed[$k], $i, $loss_rate, $formatted_first_delay_time, $first_delay_rate, $formatted_array_loss_time[0], $formatted_array_loss_time[1], $formatted_array_delay_time[0], $formatted_array_delay_time[1], $formatted_array_delay_rate[0], $formatted_array_delay_rate[1], $array_loss_episode[0], $array_loss_episode[1]\n";

	}
	}
}

close(TOTAL_OUT);


sub compute_avg_std
{
	$in =$_[0];
	open(INPUT, $in) or die "$in cannot be opened.\n";

	@my_array;#mean,std

	$counter = 0;
	$sum = 0;
	$square_sum = 0;
	$mean = 0;
	$var = 0;
	$std = 0;
	
	while($line = <INPUT>)
	{			
		chomp($line);
		$counter++;
		$sum += $line;
		$square_sum += $line**2;
        	$prev_line = $line;
	}

	$mean = $sum /$counter;
	$autocor = $square_sum/$counter;
	$var = $autocor-$mean**2;
	$std = sqrt($var);

	#$formatted_mean=sprintf("%.3f", $mean);
	#$formatted_std=sprintf("%.3f", $std);
	close(INPUT);

	$my_array[0]=$mean;
	$my_array[1]=$std;
	return @my_array;
}
